home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Mail / pine3.92 / pine / osdep / pipe.os2 < prev    next >
Text File  |  1996-03-14  |  6KB  |  166 lines

  1. #line 2 "osdep/pipe.os2"
  2. /*======================================================================
  3.     pipe
  4.     
  5.     Initiate I/O to and from a process.  These functions are similar to 
  6.     popen and pclose, but both an incoming stream and an output file are 
  7.     provided.
  8.    
  9.  ====*/
  10.  
  11. #ifndef    STDIN_FILENO
  12. #define    STDIN_FILENO    0
  13. #endif
  14. #ifndef    STDOUT_FILENO
  15. #define    STDOUT_FILENO    1
  16. #endif
  17. #ifndef    STDERR_FILENO
  18. #define    STDERR_FILENO    2
  19. #endif
  20.  
  21. short    child_signalled;
  22. short    child_jump = 0;
  23. jmp_buf    child_state;
  24.  
  25. /*----------------------------------------------------------------------
  26.      Spawn a child process and optionally connect read/write pipes to it
  27.  
  28.   Args: command -- string to hand the shell
  29.     outfile -- address of pointer containing file to receive output
  30.     errfile -- address of pointer containing file to receive error output
  31.     mode -- mode for type of shell, signal protection etc...
  32.   Returns: pointer to alloc'd PIPE_S on success, NULL otherwise
  33.  
  34.   This is a much simpler version than the UNIX pipe since it utilises
  35.   the EMX popen()/pclose() functions for OS/2 (and thereby avoides
  36.   fork() and its restrictions under OS/2). It is therefore not as
  37.   functional as the UNIX equivalents, and only understands a subset
  38.   of modes. All commands also invoke the system shell, but this is
  39.   of little consequence as there are no security problems and so forth
  40.   in the OS/2 environment.
  41.     PIPE_WRITE tells us we need to open a pipe to write the child's
  42.     stdin.
  43.     PIPE_READ tells us we need to open a pipe to read from the child's
  44.     stdout/stderr.  *NOTE*  Having neither of the above set means 
  45.     we're not setting up any pipes, just forking the child and exec'ing
  46.     the command.  Also, this takes precedence over any named outfile.
  47.     PIPE_STDERR means we're to tie the childs stderr to the same place
  48.     stdout is going.  *NOTE* This only makes sense then if PIPE_READ
  49.     or an outfile is provided.  Also, this takes precedence over any
  50.     named errfile.
  51.     PIPE_PROT means to protect the child from the usual nasty signals
  52.     that might cause premature death.  Otherwise, the default signals are
  53.     set so the child can deal with the nasty signals in its own way.     
  54.     PIPE_RESET means we reset the terminal mode to what it was before
  55.     we started pine and then exec the command.
  56.  ----*/
  57. PIPE_S *
  58. open_system_pipe(command, outfile, errfile, mode)
  59.   char  *command;
  60.   char **outfile, **errfile;
  61.   int    mode;
  62. {
  63.   PIPE_S *syspipe = NULL;
  64.   FILE   *pipefp  = NULL;
  65.  
  66.   dprint(5, (debugfile, "Opening pipe: \"%s\" (%s%s%s%s%s%s)\n",command,
  67.          (mode & PIPE_WRITE)   ? "W":"", (mode & PIPE_READ)  ? "R":"",
  68.          (mode & PIPE_NOSHELL) ? "N":"", (mode & PIPE_PROT)  ? "P":"",
  69.          (mode & PIPE_USER)    ? "U":"", (mode & PIPE_RESET) ? "T":""));
  70.  
  71.   if(outfile && !*outfile)
  72.     *outfile = temp_nam(NULL, "pp");    /* asked for, but not named? */
  73.   if(errfile && !*errfile)
  74.     *errfile = temp_nam(NULL, "pp");    /* ditto */
  75.  
  76.   syspipe = (PIPE_S *)fs_get(sizeof(PIPE_S));
  77.   memset(syspipe, 0, sizeof(PIPE_S));
  78.  
  79.   if(mode & PIPE_READ){
  80.     /* save std handles */
  81.     int wasstdin  = dup(STDIN_FILENO);
  82.     int wasstderr = dup(STDERR_FILENO);
  83.     int input     = open("NUL", S_IREAD); /* safety */
  84.     int outerr    = creat(errfile ? *errfile : "NUL", S_IREAD|S_IWRITE);
  85.     /* dup the handles */
  86.     dup2(outerr, STDERR_FILENO);
  87.     dup2(input, STDIN_FILENO);
  88.     /* now, start the pipe */
  89.     pipefp = syspipe->ifilep = popen(command, "rb");
  90.     /* revert back to the previous handles
  91.     dup2(STDIN_FILENO, wasstdin);
  92.     dup2(STDERR_FILENO, wasstderr);
  93.     /* and clean up the no-longer needed handles */
  94.     close(input);
  95.     close(outerr);
  96.   }
  97.   else {
  98.     /* save std handles */
  99.     int wasstdout = dup(STDOUT_FILENO);
  100.     int wasstderr = dup(STDERR_FILENO);
  101.     /* dup to force child to inheret them */
  102.     int output = creat(outfile ? *outfile : "NUL", S_IREAD|S_IWRITE);
  103.     int outerr = (mode & PIPE_STDERR) ? output : creat(errfile ? *errfile : "NUL", S_IREAD|S_IWRITE);
  104.     dup2(output, STDOUT_FILENO);
  105.     dup2(outerr, STDERR_FILENO);
  106.     /* Now, open the pipe */
  107.     pipefp = syspipe->ofilep = popen(command, "wb");
  108.     /* Restore parent's std filehandles and clean up */
  109.     dup2(STDOUT_FILENO, wasstdout);
  110.     dup2(STDERR_FILENO, wasstderr);
  111.     close(wasstdout);
  112.     close(wasstderr);
  113.     close(output);
  114.     if (outerr != output)
  115.       close(outerr);
  116.   }
  117.  
  118.   if (pipefp == NULL) {
  119.     q_status_message1(SM_ORDER,3,3, "Error executing external command: %s",
  120.               error_description(errno));
  121.     fs_give((void **)&syspipe);
  122.     if(outfile)
  123.       fs_give((void **)outfile);
  124.     dprint(1, (debugfile, "CAN'T OPEN PIPE TO COMMAND: %s\n", command));
  125.   }
  126.  
  127.   if (!(mode & (PIPE_WRITE|PIPE_READ))) {
  128.     flush_status_messages(0);        /* just clean up display */
  129.     ClearScreen();
  130.     fflush(stdout);
  131.     return syspipe;
  132.   }
  133.  
  134.   return(syspipe);
  135. }
  136.  
  137.  
  138.  
  139. /*----------------------------------------------------------------------
  140.     Close pipe previously allocated and wait for child's death
  141.  
  142.   Args: syspipe -- address of pointer to struct returned by open_system_pipe
  143.   Returns: returns exit status of child or -1 if invalid syspipe
  144.  ----*/
  145. int
  146. close_system_pipe(syspipe)
  147.     PIPE_S **syspipe;
  148. {
  149.     int         status = 0;
  150.  
  151.     if(!syspipe || !*syspipe)
  152.       return(-1);
  153.  
  154.     if((*syspipe)->ofilep)
  155.       status = pclose((*syspipe)->ofilep);
  156.  
  157.     if((*syspipe)->ifilep)
  158.       status = pclose((*syspipe)->ifilep);
  159.  
  160.     ClearScreen();                /* No I/O to forked child */
  161.     ps_global->mangled_screen = 1;
  162.  
  163.     fs_give((void **)syspipe);
  164.     return(status);
  165. }
  166.